From: kaf24@localhost.localdomain Date: Fri, 27 Oct 2006 17:00:03 +0000 (+0100) Subject: [HVM] Fix SMP timer issues: X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15567^2~194 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=ee82b836b35e0dc1b45f040d53be979fc9dd8361;p=xen.git [HVM] Fix SMP timer issues: * Sync AP TSCs with BP at startup * Only halt BP TSC when descheduled * Correctly handle IPIs on timer vector Signed-off-by: Xiaowei Yang --- diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index f950d05295..3a9583a4c5 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -228,7 +228,7 @@ void hvm_do_resume(struct vcpu *v) hvm_stts(v); /* pick up the elapsed PIT ticks and re-enable pit_timer */ - if ( pt->enabled && pt->first_injected ) { + if ( pt->enabled && v->vcpu_id == pt->bind_vcpu && pt->first_injected ) { if ( v->arch.hvm_vcpu.guest_time ) { hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time); v->arch.hvm_vcpu.guest_time = 0; @@ -286,6 +286,9 @@ void hvm_setup_platform(struct domain* d) pit_init(v, cpu_khz); rtc_init(v, RTC_PORT(0), RTC_IRQ); pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS); + + /* init guest tsc to start from 0 */ + hvm_set_guest_time(v, 0); } void pic_irq_request(void *data, int level) diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c index 288cf2724d..ea6f73a51d 100644 --- a/xen/arch/x86/hvm/intercept.c +++ b/xen/arch/x86/hvm/intercept.c @@ -325,6 +325,7 @@ struct periodic_time * create_periodic_time( stop_timer (&pt->timer); pt->enabled = 0; } + pt->bind_vcpu = 0; /* timer interrupt delivered to BSP by default */ pt->pending_intr_nr = 0; pt->first_injected = 0; if (period < 900000) { /* < 0.9 ms */ diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index a1ce8ddf33..28f06e66a0 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -683,7 +683,8 @@ void hvm_interrupt_post(struct vcpu *v, int vector, int type) struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm); - if ( pt->enabled && is_periodic_irq(v, vector, type) ) { + if ( pt->enabled && v->vcpu_id == pt->bind_vcpu + && is_periodic_irq(v, vector, type) ) { if ( !pt->first_injected ) { pt->pending_intr_nr = 0; pt->last_plt_gtime = hvm_get_guest_time(v); diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 88c0802425..d37ab536e6 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -761,7 +761,8 @@ static void svm_freeze_time(struct vcpu *v) { struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm; - if ( pt->enabled && pt->first_injected && !v->arch.hvm_vcpu.guest_time ) { + if ( pt->enabled && pt->first_injected && v->vcpu_id == pt->bind_vcpu + && !v->arch.hvm_vcpu.guest_time ) { v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v); stop_timer(&(pt->timer)); } diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 3892ffa1c3..e5b96ede56 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -314,14 +314,20 @@ static void vmx_set_host_env(struct vcpu *v) error |= __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom()); } +/* Update CR3, CR0, CR4, GDT, LDT, TR */ static void vmx_do_launch(struct vcpu *v) { -/* Update CR3, CR0, CR4, GDT, LDT, TR */ unsigned int error = 0; unsigned long cr0, cr4; - if (v->vcpu_id == 0) + if ( v->vcpu_id == 0 ) hvm_setup_platform(v->domain); + else { + /* Sync AP's TSC with BSP's */ + v->arch.hvm_vcpu.cache_tsc_offset = + v->domain->vcpu[0]->arch.hvm_vcpu.cache_tsc_offset; + hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset); + } __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (cr0) : ); @@ -360,9 +366,6 @@ static void vmx_do_launch(struct vcpu *v) __vmwrite(HOST_CR3, v->arch.cr3); v->arch.schedule_tail = arch_vmx_do_resume; - - /* init guest tsc to start from 0 */ - hvm_set_guest_time(v, 0); } /* diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index ac1be73556..41285d6f3c 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -458,7 +458,8 @@ static void vmx_freeze_time(struct vcpu *v) { struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm; - if ( pt->enabled && pt->first_injected && !v->arch.hvm_vcpu.guest_time ) { + if ( pt->enabled && pt->first_injected && v->vcpu_id == pt->bind_vcpu + && !v->arch.hvm_vcpu.guest_time ) { v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v); stop_timer(&(pt->timer)); } @@ -1972,6 +1973,13 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs) switch (regs->ecx) { case MSR_IA32_TIME_STAMP_COUNTER: + { + struct periodic_time *pt = + &(v->domain->arch.hvm_domain.pl_time.periodic_tm); + if ( pt->enabled && pt->first_injected + && v->vcpu_id == pt->bind_vcpu ) + pt->first_injected = 0; + } hvm_set_guest_time(v, msr_content); break; case MSR_IA32_SYSENTER_CS: diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h index ada8936af7..b4492e1d59 100644 --- a/xen/include/asm-x86/hvm/vpt.h +++ b/xen/include/asm-x86/hvm/vpt.h @@ -91,6 +91,7 @@ struct periodic_time { char one_shot; /* one shot time */ char irq; char first_injected; /* flag to prevent shadow window */ + u32 bind_vcpu; /* vcpu timer interrupt delivers to */ u32 pending_intr_nr; /* the couner for pending timer interrupts */ u32 period; /* frequency in ns */ u64 period_cycles; /* frequency in cpu cycles */